﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WokseleNaDrzewie
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ModelVisual3D modelVisual;
        private GeometryModel3D modelGeometry;
        private List<Triangle> triangles;
        private Trackball trackball;
        private Octree Tree;
        private int convex = 0;

        public MainWindow()
        {
            InitializeComponent();
            trackball = new Trackball();
            trackball.EventSource = myElement;
            viewport3D.Camera.Transform = trackball.Transform;
        }

        private void loadFileButton_Click(object sender, RoutedEventArgs e)
        {
            //LOAD FROM FILE
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.Filter = "Stl Files(*.STL)|*.STL"; // Filter files by extension

            // Show open file dialog box
            bool? result = dlg.ShowDialog();
            // Process open file dialog box results
            if (result == true)
            {
                // Open document
                string filename = dlg.FileName;
                viewport3D.Children.Clear();
                InitializeModel(filename);
                //ParseFile(filename);
            }
        }

        private double ParseValue(String[] splitVal, String[] split2)
        {
            int e;
            if (splitVal[1].Contains('e'))
            {
                split2 = splitVal[1].Split('e');
                e = Convert.ToInt32(split2[1]);
                if (splitVal[0].Length != 2)    //bez minusa przy wartości
                    return (Convert.ToDouble(splitVal[0]) + Convert.ToDouble(split2[0]) / (Math.Pow(10, split2[0].Length))) * Math.Pow(10, e);
                else

                    return (Convert.ToDouble(splitVal[0]) - Convert.ToDouble(split2[0]) / (Math.Pow(10, split2[0].Length))) * Math.Pow(10, e);
            }
            else
                if (splitVal[0].Length != 2)
                    return Convert.ToDouble(splitVal[0]) + Convert.ToDouble(splitVal[1]) / (Math.Pow(10, splitVal[1].Length));
                else
                    return Convert.ToDouble(splitVal[0]) - Convert.ToDouble(splitVal[1]) / (Math.Pow(10, splitVal[1].Length));
        }

        private void InitializeModel(string filename)
        {
            triangles = new List<Triangle>();
            modelVisual = new ModelVisual3D();
            Model3DGroup modelGroup = new Model3DGroup();
            DirectionalLight dirLight = new DirectionalLight(Colors.White, new Vector3D(1, 1, 1));
            DirectionalLight sideLight = new DirectionalLight(Colors.White, new Vector3D(-1, -1, -1));
            modelGroup.Children.Add(dirLight);
            modelGroup.Children.Add(sideLight);
            DiffuseMaterial difMat = new DiffuseMaterial(new SolidColorBrush(Colors.Red));
            MeshGeometry3D mesh = new MeshGeometry3D();
            //dodanie trójkątów:
            //1. dodawanie po kolei z pliku
            Vector3D normal = new Vector3D();
            Point3D[] points = new Point3D[3];
            using (StreamReader sr = new StreamReader(filename))
            {
                String line;
                String[] split = new String[5];
                int counter = 0;
                int ctest = 0;
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.Contains("facet normal"))
                    {
                        split = line.Split(' ');
                        String[] splitVal = new String[2];
                        splitVal = split[2].Split('.');
                        String[] split2 = new String[2];
                        normal.X = ParseValue(splitVal, split2);
                        splitVal = split[3].Split('.');
                        normal.Y = ParseValue(splitVal, split2);
                        splitVal = split[4].Split('.');
                        normal.Z = ParseValue(splitVal, split2);
                        //mesh.Normals.Add(normal);
                        continue;
                    }
                    if (line.Contains("vertex"))
                    {
                        points[counter] = new Point3D();
                        split = line.Split(' ');
                        String[] splitVal = new String[2];
                        splitVal = split[1].Split('.');
                        String[] split2 = new String[2];
                        points[counter].X = ParseValue(splitVal, split2);
                        splitVal = split[2].Split('.');
                        points[counter].Y = ParseValue(splitVal, split2);
                        splitVal = split[3].Split('.');
                        points[counter].Z = ParseValue(splitVal, split2);
                        mesh.Positions.Add(points[counter]);
                        mesh.TriangleIndices.Add(ctest);
                        ctest++;
                        counter++;
                    }
                    if (counter == 3)
                    {
                        Triangle t = new Triangle(points, normal);
                        triangles.Add(t);
                        counter = 0;
                    }
                }
            }
            //koniec dodawania
            modelGeometry = new GeometryModel3D(mesh, difMat);
            modelGroup.Children.Add(modelGeometry);
            modelVisual.Content = modelGroup;
            viewport3D.Children.Add(modelVisual);


        }

        public void vokselizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (modelGeometry == null)
            {
                MessageBox.Show("najpierw wczytaj model z pliku!");
                return;
            }
            if (Tree == null || convex != 1)
            {
                //creating Octree
                double maxSize = Math.Max(modelGeometry.Bounds.SizeX, Math.Max(modelGeometry.Bounds.SizeY, modelGeometry.Bounds.SizeZ));
                Point3D origin = modelGeometry.Bounds.Location;
                int divide = 16;
                try
                {
                    divide = int.Parse(Divide.Text);
                }
                catch
                {
                    MessageBox.Show("wpisz poprawna liczbe");
                    return;
                }

                Tree = new Octree(maxSize, origin, triangles, true, divide);
                convex = 1;
            }
            viewport3D.Children.Clear();
            viewport3D.Children.Add(Tree.ModelVisual);
        }

        public void vokselizeButton2_Click(object sender, RoutedEventArgs e)
        {
            if (modelGeometry == null)
            {
                MessageBox.Show("najpierw wczytaj model z pliku!");
                return;
            }
            if (Tree == null || convex != -1)
            {
                //creating Octree
                double maxSize = Math.Max(modelGeometry.Bounds.SizeX, Math.Max(modelGeometry.Bounds.SizeY, modelGeometry.Bounds.SizeZ));
                Point3D origin = modelGeometry.Bounds.Location;
                int divide = 16;
                try
                {
                    divide = int.Parse(Divide.Text);
                }
                catch
                {
                    MessageBox.Show("wpisz poprawna liczbe");
                    return;
                }
                Tree = new Octree(maxSize, origin, triangles, false, divide);
                convex = -1;
            }
            viewport3D.Children.Clear();
            viewport3D.Children.Add(Tree.ModelVisual);
        }


        private void baseButton_Click(object sender, RoutedEventArgs e)
        {
            viewport3D.Children.Clear();
            viewport3D.Children.Add(modelVisual);
        }

        private void myElement_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Mouse.OverrideCursor = Cursors.None;
        }

        private void myElement_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Mouse.OverrideCursor = Cursors.Arrow;
        }

        private void myElement_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            Mouse.OverrideCursor = Cursors.None;
        }

        private void myElement_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            Mouse.OverrideCursor = Cursors.Arrow;
        }

        private void Divide_TextChanged(object sender, TextChangedEventArgs e)
        {
            convex = 0;
        }
    }
}
